package com.machine.filling.net.serialPort.util;

import android.util.Log;

import com.machine.filling.net.serialPort.receive.Receive_EndFueling;
import com.machine.filling.net.serialPort.receive.Receive_MachineState;
import com.machine.filling.net.serialPort.receive.Receive_PrepareFueling;
import com.machine.filling.util.LogUtil;
import com.machine.filling.util.NumberUtil;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by Administrator on 2018/3/5 0005.
 */

public class SerialPortMsgUtil {
    /**
     * 离线超时时间 s
     */
    private final int OfflineOutTime = 5 * 1000;

    private long lastTime;

    public SerialPortMsgUtil() {
        readOffTimesMap = new HashMap<>();
    }

    /**
     * 油机状态
     */
    private static final String CMD_MACHINE_STATE_2104 = "2104";
    /**
     * 加油前准备
     */
    private static final String CMD_PREPARE_FUELING_8101 = "8101";
    /**
     * 结束加油
     */
    private static final String CMD_END_FUELING_2101 = "2101";

    /**
     * 发送定量
     */
    private static final String CMD_PRE_ORDER_110A = "110A";
    /**
     * 自助 非自助
     */
    private static final String CMD_SELF_910E = "910E";

    private static final String TAG = "解析工具类";
    private static final String startStr = "7EFE";
    private static final String endStr = "0D";

    public static String frameStart_2;
    public static String versionNum_1;
    public static String gunNum_1;
    public static String cmd_2;
    public static String length_1;
    public static String datas;
    public static String crc_datas;//用于crc计算的部分，从7efe后边到crc之前的数据进行crc计算得出crc_2的结果
    public static String crc_2;
    public static String frameEnd_1;

    private OnSerialPortMsgListener onSerialPortMsgListener;
    private int maxOffTimes = 5;//最大读取空数据次数(串口离线)
    private Map<String, Integer> readOffTimesMap;

    /**
     * 侦听 串口数据 并解析
     *
     * @param msg
     */
    public void interceptMessage(String serialNum, String msg) {
        try {
            msg = msg.toLowerCase();
            msg = msg.substring(msg.indexOf("7efe"));
            frameStart_2 = msg.substring(0, 4);
            versionNum_1 = msg.substring(4, 6);
            gunNum_1 = msg.substring(6, 8);
            cmd_2 = msg.substring(8, 12);
            switch (cmd_2) {
                case "2104":
                    //                    LogUtil.e("2104加油中/空闲/锁机/授权有卡-->" + msg);
                    break;
                case "8101":
                    LogUtil.e("8101加油前准备-->" + msg);
                    break;
                case "2101":
                    LogUtil.e("2101结束加油-->" + msg);
                    break;
                case "110A":
                    LogUtil.e("发送定量-->" + msg);
                    break;
                case "910E":
                    LogUtil.e("自助/非自助/设置屏幕参数-->" + msg);
                    break;
                case "9108":
                    LogUtil.e("查询脱机-->" + msg);
                    break;
                case "2105":
                    LogUtil.e("加油机回复-->" + msg);
                    break;
                case "1105":
                    LogUtil.e("查询总累计-->" + msg);
                    break;
                case "1104":
                    LogUtil.e("设置油机-->" + msg);
                    break;
                case "910A":
                    LogUtil.e("设置卡机-->" + msg);
                    break;
                case "910C":
                    LogUtil.e("显示屏广告信息-->" + msg);
                    break;
                case "1101":
                    LogUtil.e("下发卡信息-->" + msg);
                    break;
                case "9101":
                    LogUtil.e("下发写卡信息");
                    break;
                case "1102":
                    LogUtil.e("下发交易信息");
                    break;
                default:
            }
            length_1 = msg.substring(12, 14);
            int lengthInt = Integer.parseInt(length_1, 16);
            datas = msg.substring(14, 2 * lengthInt + 14);
            crc_datas = msg.substring(4, 2 * lengthInt + 14);
            crc_2 = msg.substring(2 * lengthInt + 14, 2 * lengthInt + 14 + 4);
            frameEnd_1 = msg.substring(2 * lengthInt + 14 + 4, 2 * lengthInt + 14 + 4 + 2);
        } catch (Exception e) {
            e.printStackTrace();
            LogUtil.e("串口指令解析失败-->" + e.getMessage());
        }
        if (!startStr.equalsIgnoreCase(frameStart_2)) {
            Log.e(TAG, serialNum + ": 帧开头错误;;" + "帧头为：---》" + frameStart_2);
            onSerialPortMsgListener.checkFrameError(serialNum, msg);

        } else if (!endStr.equalsIgnoreCase(frameEnd_1)) {
            Log.e(TAG, serialNum + ": 帧结尾错误；；帧尾为：---》" + frameEnd_1);
            onSerialPortMsgListener.checkFrameError(serialNum, msg);
        } else {

            //校验通过
            onSerialPortMsgListener.checkFramePass(serialNum, msg);
            //帧命令正确 校验通过
            if (CMD_MACHINE_STATE_2104.equalsIgnoreCase(cmd_2)) {
                if (datas.length() != 22) {
                    Log.e(TAG, serialNum + ": 油机状态更新数据域错误：==数据域为" + datas);
                    return;
                }
                Receive_MachineState cmd_state = new Receive_MachineState();
                cmd_state.setVersion_1(versionNum_1);
                cmd_state.setGunNumHead_1(gunNum_1);
                cmd_state.setStateStr(datas.substring(0, 2));
                cmd_state.setFuel_amountStr(datas.substring(2, 10));
                cmd_state.setFuel_quantityStr(datas.substring(10, 18));
                cmd_state.setUnit_priceStr(datas.substring(18, 22));
                //                LogUtil.e("油价传递下去-->"+ NumberUtil.saveTwo(NumberUtil.hexStringToAlgorism(datas.substring(18, 22))));
                onSerialPortMsgListener.onReceivedStateChanged_CMD_2104(serialNum, cmd_state);
            } else if (CMD_PREPARE_FUELING_8101.equalsIgnoreCase(cmd_2)) {//加油前的准备
                if (datas.length() != 106) {
                    Log.e(TAG, serialNum + ": 加油前准备返回数据异常：==数据为" + datas);
                    return;
                }

                Receive_PrepareFueling cmd_prepare = new Receive_PrepareFueling();
                cmd_prepare.setVersion_1(versionNum_1);
                cmd_prepare.setGun_num_head_1(gunNum_1);

                cmd_prepare.setFlagCardNum(datas.substring(0, 12));
                cmd_prepare.setCardNum(datas.substring(12, 32));
                cmd_prepare.setCardLevel(datas.substring(32, 34));
                cmd_prepare.setCardCode(datas.substring(34, 50));
                cmd_prepare.setCardType(datas.substring(50, 54));
                cmd_prepare.setDiscount(datas.substring(54, 58));
                cmd_prepare.setCarNum(datas.substring(58, 74));
                cmd_prepare.setIntegration(datas.substring(74, 82));
                cmd_prepare.setBalance_cunkuan(datas.substring(82, 90));
                cmd_prepare.setBalance_fuel_oil(datas.substring(90, 98));
                cmd_prepare.setBalance_fuel_gas(datas.substring(98, 106));
                onSerialPortMsgListener.onReceivedPrepareFueling_CMD_8101(serialNum, cmd_prepare);
                LogUtil.e("加油前准备");
            } else if (CMD_END_FUELING_2101.equalsIgnoreCase(cmd_2)) {//加油结束
                if (datas.length() != 122) {
                    Log.e(TAG, serialNum + ": 加油结束返回数据异常：==数据为：" + datas);
                    return;
                }
                Receive_EndFueling cmd_end = new Receive_EndFueling();
                cmd_end.setVersion_1(versionNum_1);
                cmd_end.setGunNumHead_1(gunNum_1);

                cmd_end.setGunNum_2(datas.substring(0, 4));
                cmd_end.setCardNum_10(datas.substring(4, 24));
                cmd_end.setSheng_8(datas.substring(24, 40));
                cmd_end.setRealMoney_9(datas.substring(40, 58));
                cmd_end.setReceivedMoney_4(datas.substring(58, 66));
                cmd_end.setErialNum_2(datas.substring(66, 70));
                cmd_end.setUnitPrice_2(datas.substring(70, 74));
                cmd_end.setLitersCumulative_4(datas.substring(74, 82));
                cmd_end.setMoneyCumlative_4(datas.substring(82, 90));
                cmd_end.setFuelingTime_7(datas.substring(90, 104));
                cmd_end.setTransactionType_1(datas.substring(104, 106));
                cmd_end.setCardLevel_1(datas.substring(106, 108));
                cmd_end.setCardType_1(datas.substring(108, 110));
                cmd_end.setLabelNum_6(datas.substring(110, 122));
                onSerialPortMsgListener.onReceivedEndFueling_CMD_2101(serialNum, cmd_end);
                LogUtil.e("加油结束");
            } else if (CMD_PRE_ORDER_110A.equalsIgnoreCase(cmd_2)) {
                //预约(发送定量)的回复帧 7EFE1002 110A 01 01 89EA0D |||| 成功01   失败02  忙 03
                onSerialPortMsgListener.onPreOrderRes_CMD_110A(serialNum, datas);
                LogUtil.e("发送定量返回-->" + datas);
            } else if (CMD_SELF_910E.equalsIgnoreCase(cmd_2)) {
                if (datas.equals("3333")) {
                    LogUtil.e("自助/非自助命令返回正确-->" + datas);
                    onSerialPortMsgListener.onIsSelfRes_CMD_910E(serialNum);
                } else {
                    Log.d(TAG, "自助非自助命令错误返回,数据域为: " + datas);
                }
            } else {
                Log.e(TAG, serialNum + ": 其他命令：==== cmd为：--" + cmd_2);
                onSerialPortMsgListener.onReceivedUnKnownCMD(serialNum, msg);
            }
        }
    }

    public void setOnSerialPortMsgListener(OnSerialPortMsgListener onSerialPortMsgListener) {
        this.onSerialPortMsgListener = onSerialPortMsgListener;
    }

    /**
     * 油机返回结果监听
     */
    public interface OnSerialPortMsgListener {
        /**
         * 镇校验错误，
         *
         * @param frameMsg 命令帧
         */
        void checkFrameError(String serialNum, String frameMsg);

        /**
         * 校验通过
         *
         * @param frameMsg
         */
        void checkFramePass(String serialNum, String frameMsg);

        /**
         * 油机状态改变
         *
         * @param machineState
         */
        void onReceivedStateChanged_CMD_2104(String serialNum, Receive_MachineState machineState);

        /**
         * 加油前准备
         *
         * @param prepare_fueling
         */
        void onReceivedPrepareFueling_CMD_8101(String serialNum, Receive_PrepareFueling prepare_fueling);

        /**
         * 其他命令帧
         *
         * @param serialNum
         * @param cmdStr
         */
        void onReceivedUnKnownCMD(String serialNum, String cmdStr);

        /**
         * 结束加油
         *
         * @param cmd_end
         */
        void onReceivedEndFueling_CMD_2101(String serialNum, Receive_EndFueling cmd_end);

        /**
         * 发送定量
         *
         * @param portNum
         * @param datas
         */
        void onPreOrderRes_CMD_110A(String portNum, String datas);

        /**
         * 自助非自助返回帧
         *
         * @param portNum
         */
        void onIsSelfRes_CMD_910E(String portNum);
    }
}
